package de.swm.gwt.client;

import java.util.ArrayList;
import java.util.List;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;

import com.google.gwt.editor.client.EditorError;
import com.google.gwt.user.client.ui.UIObject;

import de.swm.gwt.client.authorization.IAccessRight;
import de.swm.gwt.client.authorization.IRightsDependentUIUpdater;
import de.swm.gwt.client.utils.ConstraintViolationEditorErrorAdapter;

/**
 * Abstrakte Basisklasse fuer Formulare.
 *
 * @param <DTO> Das DTO, das in diesem Formular gepflegt wird
 * @author Florian Rodler, Daniel Wiese
 * @copyright SWM Service GmbH, 2013-2014
 */
public abstract class AbstractForm<DTO> extends AbstractBaseForm<DTO> implements IForm<DTO> {

	private IRightsDependentUIUpdater accessRightsChecker;

	private Validator validator = Validation.buildDefaultValidatorFactory().getValidator();


	/**
	 * Erzeugt ein abstraktes Form.
	 *
	 * @param accessRightsChecker der in das konkrete Form injizierte accessRightsChecker
	 */
	public AbstractForm(IRightsDependentUIUpdater accessRightsChecker) {
		super();
		this.accessRightsChecker = accessRightsChecker;
	}

	
	/**
	 * Liefert den Validator aus dem konkreten Formular.
	 *
	 * @return der Validator.
	 */
	public Validator getValidator() {
		return validator;
	}

	/**
	 * Registriert ein UI-Objekt mit den Ausfuehrungsrechten.
	 * <p/>
	 * Registrierte UI-Objekte werden entsprechend den Ausfuehrungsrechten aktiviert oder deaktiviert.
	 *
	 * @param uiObject       das UI-Objekt
	 * @param executionRight die Ausfuehrungsrechte.
	 */
	protected void registerAccessRight(UIObject uiObject, IAccessRight executionRight) {
		accessRightsChecker.register(uiObject, executionRight);
	}


	/**
	 * Validiert das Formular und zeigt Fehlermeldungen ggf. direkt an.
	 *
	 * @return true wenn das Formular valide ist.
	 */
	public boolean validate() {
		DTO entity = this.getDisplayedDTO();
		if (entity != null && this.dtoEditor != null) {
			List<ConstraintViolation<?>> violationsToDisplay = new ArrayList<ConstraintViolation<?>>();
			//Zuerst Violations des Validators sammeln
			violationsToDisplay.addAll(getValidator().validate(entity));
			//Dann die Errors vom Editor sammeln (falsche Eingabewerte)
			if (this.dtoEditor.hasErrors()) {
				for (EditorError ee : this.dtoEditor.getErrors()) {
					violationsToDisplay.add(new ConstraintViolationEditorErrorAdapter<DTO>(ee, entity));
				}
			}
			//und am Schluss Violations anzeigen.
			if (!violationsToDisplay.isEmpty()) {
				this.dtoEditor.setConstraintViolations(violationsToDisplay);
				return false;
			}
		}
		return true;
	}

}
